#include "StatusServiceImpl.h"
#include "const.h"
#include "ConfigMgr.h"
#include "boost/uuid/uuid.hpp"
#include "boost/uuid/uuid_generators.hpp"
#include "boost/uuid/uuid_io.hpp"
#include <sstream>
#include "RedisMgr.h"
//利用boost库的uuid生成一个唯一的token
std::string GenerateUniqueTOken()
{
    boost::uuids::random_generator gen;
    boost::uuids::uuid uuid = gen();
    return boost::uuids::to_string(uuid);
}



::grpc::Status StatusServiceImpl::GetChatServer(::grpc::ServerContext* context, 
        const ::message::GetChatServerRequest* request, ::message::GetChatServerResponse* response)
{
    std::string prefix("status server has received : ");
    const auto& server = getChatServer();

    /**
     *  int32 error = 1;
        string host=2;
        string port=3;
        string token=4;
     */
    response->set_error(ErrorCodes::Success);
    response->set_host(server.host);
    response->set_port(server.port);
    response->set_token(GenerateUniqueTOken());
    //将request中带来的uid放入map中，与token关联起来
    InsertToken(request->uid(),response->token());
    return ::grpc::Status::OK;
}


StatusServiceImpl::StatusServiceImpl()
:server_index_(0)
{
    auto& cfg = ConfigMgr::GetInstance();

    std::string server_list = cfg["chatservers"]["Name"];
    std::stringstream ss(server_list);
    std::string server;

    std::vector<std::string> servers;
    while(std::getline(ss,server,','))
    {
        servers.push_back(server);
    }

    for(const auto &serverName: servers)
    {
        if(cfg[serverName]["Name"].empty()) continue;
        ChatServer server;
        server.host = cfg[serverName]["Host"];
        server.port = cfg[serverName]["Port"];
        server.name = cfg[serverName]["Name"];
        server.con_count = 0;
        chat_servers_[server.name] = server;
    }
    
}

void StatusServiceImpl::InsertToken(int uid,const std::string& token)
{
    
    //将用户token放入redis中
    RedisMgr::GetInstance()->Set(USERTOKENPREFIX+std::to_string(uid),token);
}


::grpc::Status StatusServiceImpl::Login(::grpc::ServerContext* context, 
            const ::message::LoginRequest* request, ::message::LoginResponse* response)
{

    response->set_uid(request->uid());
    response->set_token(request->token());

    int uid = request->uid();
    std::string token="";
    

    // 直接到redis中查询用户数据
    bool success = RedisMgr::GetInstance()->Get(USERTOKENPREFIX+std::to_string(uid),token);
    // 未找到token
    if(!success)
    {
        response->set_error(ErrorCodes::TokenInvalid);
        return ::grpc::Status::OK;
    }
    
    // token匹配成功
    if(token == request->token())
    {
        response->set_error(ErrorCodes::Success);
        return ::grpc::Status::OK;
    }
    // token不匹配
    
    response->set_error(ErrorCodes::TokenInvalid);
    return ::grpc::Status::OK;
}

ChatServer StatusServiceImpl::getChatServer()
{
    std::lock_guard<std::mutex> lock(_server_mtx);
    auto miniLinkCountServer = chat_servers_.begin()->second;
    //从redis中查找当前服务器连接的数量
    std::string count_str = RedisMgr::GetInstance()->HGet(LOGIN_COUNT,miniLinkCountServer.name);
    if(count_str.empty())
    {
        //没找到表示当前服务器没在线，将连接数设置为最大
        miniLinkCountServer.con_count = INT_MAX;
    }
    else
    {
        miniLinkCountServer.con_count = std::stoi(count_str);
    }

    //使用for循环查找连接数最小的chatserver服务器
    for(auto& server:chat_servers_)
    {
        if (server.second.name == miniLinkCountServer.name)
        {
            continue;
        }
        //从redis中获取chatserver的连接数 并更新到server.second中
        auto count_str = RedisMgr::GetInstance()->HGet(LOGIN_COUNT,server.second.name);

        if(count_str.empty())
        {
            //没找到表示当前服务器没在线，将连接数设置为最大
            server.second.con_count = INT_MAX;
        }
        else
        {
            server.second.con_count = std::stoi(count_str);
        }

        if (server.second.con_count<miniLinkCountServer.con_count)
        {
            miniLinkCountServer = server.second;
        }
        
    }

    return miniLinkCountServer;
}